feat(config,stack): add auto_expose_new_tables configuration option#5239
Open
avallete wants to merge 4 commits into
Open
feat(config,stack): add auto_expose_new_tables configuration option#5239avallete wants to merge 4 commits into
avallete wants to merge 4 commits into
Conversation
…fault privileges Cloud now exposes a "Default privileges for new entities" toggle that, when disabled, revokes the default GRANTs to anon/authenticated/service_role on schema public so freshly-created tables, views, sequences, and functions are not reachable through the Data API without explicit GRANTs (supabase/supabase discussion #45329). Local Supabase had no equivalent: bootstrap always installed the default GRANTs, forcing users who opted in on cloud to keep their local schema out of sync or ship a project-specific revoke migration. Add an opt-in flag under [api] with default true (preserving today's local behaviour) and have the local DB bootstrap run the same revoke SQL Studio runs at cloud project creation when the flag is false. The flag is wired through both the Go CLI (covering `supabase db reset` and legacy `supabase start`) and the TypeScript stack bootstrap (covering the new `supabase start` foreground/background flows in apps/cli/next). https://claude.ai/code/session_011pZGRjHtkxjt1iZj5LYrqq
Coverage Report for CI Build 25804246988Coverage decreased (-0.01%) to 63.748%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions15 previously-covered lines in 3 files lost coverage.
Coverage Stats
💛 - Coveralls |
Fixes the "Check code quality" job failure on PR #5239 — the new [api].auto_expose_new_tables test block was committed in a non-canonical shape and oxfmt --check rejected it. https://claude.ai/code/session_011pZGRjHtkxjt1iZj5LYrqq
…precation window The flag now models three explicit states so we can roll out the cloud default change without surprising existing users: - unset (default today): keep long-standing local behaviour, i.e. the bundled initial-schema GRANTs to anon/authenticated/service_role on schema public remain in place. - explicit true: opt-in to today's behaviour. Treated identically to unset for now; the May 30 rollout will warn that the flag is being deprecated. - explicit false: revoke the default Data API GRANTs so newly-created entities in public require explicit GRANTs to surface, matching the new cloud default. On 2026-05-30 the implicit default for unset will flip to false and the CLI will warn on explicit true. The field is removed entirely in 2026-10-30 once the revoked behaviour is permanent. - Go: api.AutoExposeNewTables is now *bool with omitempty so unset round-trips as a missing key. NewConfig no longer seeds a default; ApplyApiPrivileges treats nil and true identically and runs the revoke SQL only when an explicit false is set. - TS: api.auto_expose_new_tables is Schema.optionalKey without a decoding default. start.command.ts reads the field via `?? true` so today's nil-as-true semantics live in one place. - config.toml template now ships the field commented out with a brief timeline so users discover it without having it injected on init. https://claude.ai/code/session_011pZGRjHtkxjt1iZj5LYrqq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a new
[api].auto_expose_new_tablesconfiguration option to control whether newly-created tables, views, sequences, and functions in thepublicschema are reachable through the Data API roles (anon,authenticated,service_role) without explicit GRANTs.Why
Cloud now exposes a "Default privileges for new entities" toggle (supabase/supabase#45329). When it is off, Studio revokes the default GRANTs on
publicat project creation so the Data API surface is opt-in per entity. Local Supabase had no equivalent: bootstrap always installed the default GRANTs, forcing users who opted in on cloud to either keep their local schema out of sync or ship a project-specific revoke migration. This adds a first-classconfig.tomlflag and applies the same revoke SQL Studio runs.Migration design — tri-state field
The field is intentionally optional today so the rollout can flip the implicit default without losing track of users who made an explicit choice:
initdefault)truefalseapi.AutoExposeNewTablesis*boolwithomitempty, so unset round-trips as a missing key.NewConfigdoes not seed a value;ApplyApiPrivilegestreatsnilandtrueidentically and runs the revoke SQL only when an explicitfalseis set.api.auto_expose_new_tablesisSchema.optionalKey(Schema.Boolean)with no decoding default. The single read site (start.command.ts) uses?? true, so today's nil-as-true semantics live in one place.initconfig.toml template ships the field commented out with a brief timeline so users discover it without having a value injected.Implementation
Config schema
packages/config/src/api.ts: optional boolean with timeline-bearing description.apps/cli-go/pkg/config/api.go:*boolwithtoml:",omitempty".apps/cli-go/pkg/config/templates/config.toml: commented-out example with the rollout timeline.Database bootstrap
REVOKE_DEFAULT_DATA_API_PRIVILEGES_SQLmirrors exactly what Studio runs at cloud project creation when the toggle is off (revokesselect,insert,update,delete on tables,usage,select on sequences,execute on functionsfromanon,authenticated,service_role).internal/db/start/start.go): newApplyApiPrivilegesruns the SQL when an explicitfalseis set. Called fromSetupDatabase(covers v15 start, v15 reset, and v14 start viaSetupLocalDatabase) and frominternal/db/reset/reset.go'sinitDatabase(covers the v14-only reset path that bypassesSetupDatabase).packages/stack/src/services/postgres-init.ts): the revoke block is appended to the postgres-init script only when the resolvedautoExposeNewTablesis false, inside the same first-init branch sodb reset(which wipes the data dir) replays it.Stack wiring (TS)
PostgresConfig/ResolvedPostgresConfiggainautoExposeNewTables.createStack.tsdefaults totrueif the field is absent from the input config.StackBuilder.tspasses the resolved value intomakePostgresInitService.apps/cli/src/next/commands/start/start.command.tsreadsProjectContext.rawProjectConfig.api.auto_expose_new_tablesand threads it through, falling back totruewhen the project config or the field itself is absent.Tests
TestApiAutoExposeNewTablesDefault(asserts the field stays nil on a freshNewConfig), a newTestSetupDatabasecase that mocks the exact statement ordering when the flag isfalse, refreshedTestApiDiff/detects_differencessnapshot.packages/config/src/project.unit.test.tsround-trips unset/true/false throughconfig.toml.packages/stack/src/services/services.unit.test.tsasserts the postgres-init script contains/omits the revoke block in each flag state. ExistingStack/StackBuilderfixtures updated for the new resolved field.Out of scope (tracked separately)
supabase config pushround-trip to the Management APIsupabase linkdrift detection for this fieldapps/docsconfig reference entryCloses: CLI-1454
https://claude.ai/code/session_011pZGRjHtkxjt1iZj5LYrqq